using System;
using System.Collections;
using System.Diagnostics;
using System.Text;
using ActiproSoftware.SyntaxEditor.Addons.Simple.Ast;

namespace ActiproSoftware.SyntaxEditor.Addons.Simple.Ast {

	/// <summary>
	/// Represents a Simple language compilation unit.
	/// </summary>
	public class CompilationUnit : ActiproSoftware.SyntaxEditor.Addons.Simple.Ast.AstNode, ICompilationUnit, ISemanticParseData {

		private System.String	sourceKey;

		private bool						hasLanguageTransitions;
		private ArrayList					syntaxErrors;

		/// <summary>
		/// Gets the context ID for the collection of functions.
		/// </summary>
		public const byte FunctionContextID = ActiproSoftware.SyntaxEditor.Addons.Simple.Ast.AstNode.AstNodeContextIDBase;

		/// <summary>
		/// Gets the minimum context ID that should be used in your code for AST nodes inheriting this class.
		/// </summary>
		/// <remarks>
		/// Base all your context ID constants off of this value.
		/// </remarks>
		protected const byte CompilationUnitContextIDBase = ActiproSoftware.SyntaxEditor.Addons.Simple.Ast.AstNode.AstNodeContextIDBase + 1;

		/////////////////////////////////////////////////////////////////////////////////////////////////////
		// OBJECT
		/////////////////////////////////////////////////////////////////////////////////////////////////////

		/// <summary>
		/// Initializes a new instance of the <c>CompilationUnit</c> class. 
		/// </summary>
		public CompilationUnit() {}

		/// <summary>
		/// Initializes a new instance of the <c>CompilationUnit</c> class. 
		/// </summary>
		/// <param name="textRange">The <see cref="TextRange"/> of the AST node.</param>
		public CompilationUnit(TextRange textRange) : base(textRange) {}

		/////////////////////////////////////////////////////////////////////////////////////////////////////
		// PUBLIC PROCEDURES
		/////////////////////////////////////////////////////////////////////////////////////////////////////

		/// <summary>
		/// Accepts the specified visitor for visiting this node.
		/// </summary>
		/// <param name="visitor">The visitor to accept.</param>
		/// <remarks>This method is part of the visitor design pattern implementation.</remarks>
		protected override void AcceptCore(AstVisitor visitor) {
			if (visitor.OnVisiting(this)) {
				// Visit children
				if (this.ChildNodeCount > 0)
					this.AcceptChildren(visitor, this.ChildNodes);
			}
			visitor.OnVisited(this);
		}
		
		/// <summary>
		/// Gets the <see cref="SimpleNodeType"/> that identifies the type of node.
		/// </summary>
		/// <value>The <see cref="SimpleNodeType"/> that identifies the type of node.</value>
		public override SimpleNodeType NodeType { 
			get {
				return SimpleNodeType.CompilationUnit;
			}
		}

		/// <summary>
		/// Gets the collection of functions.
		/// </summary>
		/// <value>The collection of statements.</value>
		public IAstNodeList Functions {
			get {
				return new AstNodeListWrapper(this, CompilationUnit.FunctionContextID);
			}
		}

		/// <summary>
		/// Gets or sets the string-based key that identifies the source of the code, which typically is a filename.
		/// </summary>
		/// <value>The string-based key that identifies the source of the code, which typically is a filename.</value>
		public System.String SourceKey {
			get {
				return sourceKey;
			}
			set {
				sourceKey = value;
			}
		}

		/// <summary>
		/// Returns whether an <see cref="CollapsibleNodeOutliningParser"/> should visit the child nodes of the specified <see cref="IAstNode"/>
		/// to look for collapsible nodes.
		/// </summary>
		/// <param name="node">The <see cref="IAstNode"/> to examine.</param>
		/// <returns>
		/// <c>true</c> if the child nodes should be visited; otherwise, <c>false</c>.
		/// </returns>
		bool ICompilationUnit.ShouldVisitChildNodesForOutlining(IAstNode node) {
			return true;
		}
		
		/// <summary>
		/// Adds any extra <see cref="CollapsibleNodeOutliningParserData"/> nodes to the <see cref="CollapsibleNodeOutliningParser"/>,
		/// such as for comments that should be marked as collapsible.
		/// </summary>
		/// <param name="outliningParser">The <see cref="CollapsibleNodeOutliningParser"/> to update.</param>
		void ICompilationUnit.UpdateOutliningParser(CollapsibleNodeOutliningParser outliningParser) {
		}
		
		/// <summary>
		/// Gets whether the compilation unit contains errors.
		/// </summary>
		/// <value>
		/// <c>true</c> if the compilation unit contains errors.
		/// </value>
		public bool HasErrors {
			get {
				return ((syntaxErrors != null) && (syntaxErrors.Count > 0));
			}
		}
		
		/// <summary>
		/// Gets or sets whether the compilation unit contains any language transitions.
		/// </summary>
		/// <value>
		/// <c>true</c> if the compilation unit contains any language transitions; otherwise, <c>false</c>.
		/// </value>
		public bool HasLanguageTransitions {
			get {
				return hasLanguageTransitions;
			}
			set {
				hasLanguageTransitions = value;
			}
		}
		
		/// <summary>
		/// Gets whether the AST node is a language root node.
		/// </summary>
		/// <value>
		/// <c>true</c> if the AST node is a language root node; otherwise, <c>false</c>.
		/// </value>
		/// <remarks>
		/// When in a scenario where AST node trees from multiple languages have been merged together,
		/// it is useful to identify where child language AST node trees begin within their parents.
		/// </remarks>
		public override bool IsLanguageRoot {
			get {
				return true;
			}
		}
		
		/// <summary>
		/// Gets the collection of syntax errors that were found in the compilation unit.
		/// </summary>
		/// <value>The collection of syntax errors that were found in the compilation unit.</value>
		public IList SyntaxErrors {
			get {
				if (syntaxErrors == null)
					syntaxErrors = new ArrayList();
				
				return syntaxErrors;
			}
		}

	}

}
